<template>
  <div class="w-input" :class="{validate: validate, error: hasError}">
    <span class="error-tip" v-show="hasError" v-text="errorText"></span>
    <span class="rule-tip" v-show="!hasError" v-text="tip"></span>
    <textarea v-if="type==='textarea'" class="form-control" ref="input"
      :value="value"
      :name="name"
      :maxlength="maxlength"
      :disabled="disabled"
      :placeholder="holder"
      @input="onUpdateValue($event.target.value)"
      @blur="onValidate"
      @focus="hasError = false">
    </textarea>
    <input v-if="type==='password'" class="form-control" ref="input"
      type="password"
      :value="value"
      :name="name"
      :maxlength="maxlength"
      :disabled="disabled"
      :placeholder="holder"
      @input="onUpdateValue($event.target.value)"
      @blur="onValidate"
      @focus="hasError = false">
    <input v-if="type==='text'" class="form-control" ref="input"
      type="text"
      :value="value"
      :name="name"
      :maxlength="maxlength"
      :disabled="disabled"
      :placeholder="holder"
      @input="onUpdateValue($event.target.value)"
      @blur="onValidate"
      @change="onChange"
      @focus="hasError = false">
  </div>
</template>

<script>
  import Rule from './rule'
  export default {
    props: {
      value: {
        type: [String, Number],
        default: ''
      },
      type: {
        type: String,
        default: 'text'
      },
      name: {
        type: String,
        default: null
      },
      maxlength: {
        type: Number,
        default: null
      },
      validate: {
        type: Boolean,
        default: true
      },
      rule: {
        type: String,
        default: 'isEmpty|isMobile'
      },
      error: {
        type: String,
        default: '姓名不能为空|请输入正确的手机号'
      },
      disabled: {
        type: Boolean,
        default: false
      },
      tip: {
        type: String,
        default: ''
      },
      holder: {
        type: String,
        default: ''
      }
    },
    data() {
      return {
        inputVal: '',
        validateArr: [],
        hasError: false,
        errorText: ''
      }
    },
    created() {
      this._mergeValidateArr()
    },
    methods: {
      onUpdateValue(val) { // 每次输入更新value，并过滤前后空格
        let trimVal = val.trim()
        if (trimVal != val) {
          this.$refs.input.value = trimVal
        }
        this.$emit('input', trimVal)
      },
      onValidate() { // 鼠标失去焦点进行验证
        if (this.validate) {
          this._validateInput()
        }
        this.$emit('on-blur')
      },
      onChange() { // 更改input框的值时进行验证
        if (this.validate) {
          this._validateInput()
        }
        this.$emit('on-change')
      },
      _validateInput() { // 进行验证
        const aValidate = this.validateArr
        let errMsg = ''
        for (let i = 0; i < aValidate.length; i++) {
          const pattern = aValidate[i].pattern
          const aPattern = pattern.split(':')
          if (aPattern.length === 1) {
            errMsg = Rule[pattern](this.value, aValidate[i].errorText)
          } else {
            errMsg = Rule[aPattern[0].toString()](this.value, aPattern[1].toString(), aValidate[i].errorText)
          }
          if (errMsg) {
            this.hasError = true
            this.errorText = errMsg
            return true
          } else {
            this.hasError = false
            errMsg = null
          }
        }
      },
      _mergeValidateArr() { // 合并验证规则
        const aRule = this.rule.split('|')
        const aValid = this.error.split('|')
        aRule.forEach((item, index) => {
          this.validateArr.push({
            pattern: item,
            errorText: aValid[index]
          })
        })
      }
    }
  }
</script>

<style lang="scss">
  @import '../../scss/_var.scss';
  .w-input {
    position: relative;
    &.error {
      .form-control {
        transition: all .1s;
        border-color: $color-error;
      }
    }
    .error-tip {
      position: absolute;
      margin-top: 32px;
      color: $color-error;
    }
    .rule-tip {
      position: absolute;
      margin-top: 32px;
      color: $color-gray;
    }
  }
</style>